package busterminal.command.route;

import busterminal.command.AbstractCommand;
import busterminal.entity.Route;
import busterminal.entity.StoppingPoint;
import busterminal.entity.service.RouteType;
import busterminal.exception.BusinessException;
import busterminal.persistence.RouteDAO;
import busterminal.persistence.StoppingPointDAO;
import busterminal.services.ServiceLocator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Класс, реализующий действие: обновить информацию про маршрут
 */
public class UpdateRouteCommand extends AbstractCommand {

    /**
     * Имя параметра "Идентификатор модели"
     */
    private final static String PARAM_ROUTE_ID = "Route ID";
    /**
     * Имя параметра "Новый номер маршрута"
     */
    public final static String PARAM_NEW_ROUTE_NUMBER = "New route number";
    /**
     * Имя параметра "Новое название маршрута"
     */
    public final static String PARAM_NEW_ROUTE_NAME = "New route name";
    /**
     * Имя параметра "Новое начало маршрута"
     */
    public final static String PARAM_NEW_START_POINT_ID = "New start point id";
    /**
     * Имя параметра "Новый конец маршрута"
     */
    public final static String PARAM_NEW_END_POINT_ID = "New end point id";
    /**
     * Имя параметра "Новый список промежуточных остановочных пунктов"
     */
    public final static String PARAM_NEW_INTERMEDIATE_STOPPING_POINTS_ID = "New intermediate stopping point(s) id (separated by comma)";
    /**
     * Имя параметра "Новый тип маршрута"
     */
    public final static String PARAM_NEW_ROUTE_TYPE = "New route type";
    /**
     * Разделитель для параметра "Новый список промежуточных остановочных пунктов"
     */
    private final static String SEPARATOR = " *[,] *";

    /**
     * Конструктор по умолчанию
     */
    public UpdateRouteCommand() {
        super("Update info about route");
    }

    /**
     * Выполнить команду: обновить информацию про маршрут (изменение номера маршрута)
     */
    @Override
    public void execute() {
        RouteDAO routeDAO = ServiceLocator.getService(RouteDAO.class);
        String parametrId = parameters.get(PARAM_ROUTE_ID);
        int ID;
        try {
            ID = Integer.parseInt(parametrId);
        } catch (Exception e) {
            throw new BusinessException("Invalid route ID='" + parametrId + "';" + e.toString(), e);
        }
        Route route = routeDAO.read(ID);
        route.setRouteNumber(parameters.get(PARAM_NEW_ROUTE_NUMBER));
        
        String paramRouteName = parameters.get(PARAM_NEW_ROUTE_NAME);
        route.setRouteName(paramRouteName);
        
        String paramStartPointId = parameters.get(PARAM_NEW_START_POINT_ID);
        int startPointId;
        try {
            startPointId = Integer.parseInt(paramStartPointId);
        } catch (Exception e) {
            throw new BusinessException("Invalid start point id='" + paramStartPointId + "'; " + e.toString(), e);
        }
        StoppingPoint startStoppingPoint = ServiceLocator.getService(StoppingPointDAO.class).read(startPointId);
        route.setStartPoint(startStoppingPoint);
        
        String paramEndPointId = parameters.get(PARAM_NEW_END_POINT_ID);
        int endPointId;
        try {
            endPointId = Integer.parseInt(paramEndPointId);
        } catch (Exception e) {
            throw new BusinessException("Invalid end point id='" + paramEndPointId + "'; " + e.toString(), e);
        }
        StoppingPoint endStoppingPoint = ServiceLocator.getService(StoppingPointDAO.class).read(endPointId);
        route.setEndPoint(endStoppingPoint);
        
        List<String> inputData = Arrays.asList(parameters.get(PARAM_NEW_INTERMEDIATE_STOPPING_POINTS_ID).split(SEPARATOR));
        ArrayList<StoppingPoint> foundStoppingPoints = new ArrayList<StoppingPoint>();
        for (String stoppingPoint : inputData) {
            int stoppingPointId;
            try {
                stoppingPointId = Integer.parseInt(stoppingPoint);
            } catch (Exception e) {
                throw new BusinessException("Incorrect stopping point id: '" + stoppingPoint + "'; " + e.toString(), e);
            }
            StoppingPoint intermediateStoppingPoint = ServiceLocator.getService(StoppingPointDAO.class).read(stoppingPointId);
            foundStoppingPoints.add(intermediateStoppingPoint);
        }
        route.setIntermediateStoppingPointsList(foundStoppingPoints);
        
        try {
            route.setRouteType(RouteType.valueOf(parameters.get(PARAM_NEW_ROUTE_TYPE).toUpperCase()));
        } catch (Exception e) {
            throw new BusinessException("Incorrect route type: '" + parameters.get(PARAM_NEW_ROUTE_TYPE) + "'; " + e.toString(), e);
        }              
        
        routeDAO.update(route);
    }

    /**
     * Получить список имён параметров
     * @return список имён параметров
     */
    @Override
    public List<String> getParametersNames() {
        return Arrays.asList(PARAM_ROUTE_ID, PARAM_NEW_ROUTE_NUMBER, PARAM_NEW_ROUTE_NAME, PARAM_NEW_START_POINT_ID, PARAM_NEW_END_POINT_ID, PARAM_NEW_INTERMEDIATE_STOPPING_POINTS_ID, PARAM_NEW_ROUTE_TYPE);
    }
    
    /**
     * Вывести список доступных вариантов параметра с фиксированным набором значений
     * @param parameterName имя параметра с фиксированным набором значений
     */
    @Override
    public void showAccessableVariants(String parameterName) {
        if (PARAM_NEW_ROUTE_TYPE.equals(parameterName)) {
            System.out.println("Accessable variants: " + RouteType.getValues());
        }
    }    
    
}
